<?php
class View {
    protected $sections = [];
    protected $extends;
    protected $cachePath = __DIR__ . '/cache/';

    public function __construct() {
        if (!is_dir($this->cachePath)) {
            mkdir($this->cachePath, 0777, true);
        }
    }

    public function render($file, $data = []) {
        $compiled = $this->compileFile($file);

        extract($data, EXTR_SKIP);

        ob_start();
        include $compiled;
        return ob_get_clean();
    }

    protected function compileFile($file) {
        $cacheFile = $this->cachePath . md5($file) . '.php';

        // 如果模板被修改过，才重新编译
        if (!file_exists($cacheFile) || filemtime($cacheFile) < filemtime($file)) {
            $content = file_get_contents($file);
            $content = $this->compile($content);
            file_put_contents($cacheFile, $content);
        }

        return $cacheFile;
    }

    protected function compile($code) {
        // @extends('file')
        $code = preg_replace_callback('/@extends\(\'(.+?)\'\)/', function($m) {
            $this->extends = $m[1];
            return "<?php include \$this->compileFile('{$m[1]}'); ?>";
        }, $code);

        // @section('name') ... @endsection
        $code = preg_replace_callback('/@section\(\'(.+?)\'\)(.*?)@endsection/s', function($m) {
            $name = $m[1];
            $content = $m[2];
            return "<?php \$this->sections['$name'] = <<<'EOT'\n$content\nEOT;\n?>";
        }, $code);

        // @yield('name')
        $code = preg_replace_callback('/@yield\(\'(.+?)\'\)/', function($m) {
            $name = $m[1];
            return "<?php echo \$this->sections['$name'] ?? ''; ?>";
        }, $code);

        // @include('file')
        $code = preg_replace('/@include\(\'(.+?)\'\)/', "<?php include \$this->compileFile('$1'); ?>", $code);

        // {{ $var }} → 转义
        $code = preg_replace('/\{\{\s*(.+?)\s*\}\}/', "<?php echo htmlspecialchars($1, ENT_QUOTES, 'UTF-8'); ?>", $code);

        // {!! $var !!} → 原样
        $code = preg_replace('/\{!!\s*(.+?)\s*!!\}/', "<?php echo $1; ?>", $code);

        // 控制语句
        $code = preg_replace('/@if\s*\((.+?)\)/', "<?php if ($1): ?>", $code);
        $code = preg_replace('/@elseif\s*\((.+?)\)/', "<?php elseif ($1): ?>", $code);
        $code = preg_replace('/@else/', "<?php else: ?>", $code);
        $code = preg_replace('/@endif/', "<?php endif; ?>", $code);

        $code = preg_replace('/@foreach\s*\((.+?)\)/', "<?php foreach ($1): ?>", $code);
        $code = preg_replace('/@endforeach/', "<?php endforeach; ?>", $code);

        $code = preg_replace('/@for\s*\((.+?)\)/', "<?php for ($1): ?>", $code);
        $code = preg_replace('/@endfor/', "<?php endfor; ?>", $code);

        return $code;
    }
}
